/**
 * @copyright Copyright (c) 2025 CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author Xie Jinhui
 */
/* 
 * Include standard C library headers for string operations, file I/O, and system calls
 * These headers provide essential functions for memory management, string manipulation, and process control
 */
#include <string.h>
#include <unistd.h>
#include <stdio.h>

/* 
 * Include application-specific headers for function declarations and data structures
 * These headers define the interface between different modules of the application control system
 */
#include "app_execute.h"
#include "app_action.h"
#include "mqtt_client.h"
#include "common.h"
#include "appprofile_manage.h"

/* 
 * Define the program name constant used for process identification and error reporting
 * This name is used when checking if the program is already running to prevent multiple instances
 */
#define PROGRAM_NAME "appctl"

/* 
 * Define directory paths for temporary file operations and package management
 * UZIP_ROOT_DIR: Root directory for temporary operations
 * UZIP_DIR: Specific directory for application control temporary files
 * APP_PACK_PAR: Directory path for application packages
 * APP_PACK_BACKUP: Backup directory for shared application packages
 * CONTAINER_UZINP_PATH: Container unzip path for temporary operations
 */
#define UZIP_ROOT_DIR "/tmp"
#define UZIP_DIR "/tmp/appctl"
#define APP_PACK_PAR "/apps"
#define APP_PACK_BACKUP "/apps/share"
#define CONTAINER_UZINP_PATH "/tmp"

/* 
 * Define size constants for buffers and directory operations
 * DIR_SIZE: Maximum size for directory path strings
 * MAX_NODES: Maximum number of application nodes that can be handled
 * CHUNK_SIZE: Buffer size for file operations (10KB chunks)
 */
#define DIR_SIZE 256
#define MAX_NODES 128
#define CHUNK_SIZE (1024*10)  // 缓冲区大小

/* 
 * Define error message constants for various failure scenarios
 * These strings are used to identify specific error conditions from MQTT responses
 */
#define AUTHEN_FAIL "AuthentificationFail"       //鉴权失败
#define FILE_SIGN_ERROR "FileSignatureError"     //文件验签错误
#define FILE_NOT_EXIST "FileNotExist"            //文件不存在

/* 
 * Define application operation error message constants
 * These strings identify errors related to application control operations
 */
#define EXCUTE_ERROR "ExcuteError"              //动作执行失败 
#define APP_NOT_EXIST "AppNotExist"              //应用不存在

/* 
 * Define maximum application capacity constant
 * This limits the number of applications that can be managed by the system
 */
#define APP_MAX_AMOUNT 64

/* 
 * Define default application name constant
 * This name is used when no specific application is specified in operations
 */
#define DEFAULE_APP_NAME "appctl"

/* 
 * Define application profile information node constant
 * This string identifies the application name field in JSON configuration files
 */
#define APPNAME    "appname" //appprofile信息节点

/*******************************应用操作函数**********************************/

/* 
 * Declare static function prototypes for all application control operations
 * These functions handle the core functionality of the application control system
 */
static int app_install(struct app_action *app_args);
static int app_uninstall(struct app_action *app_args);
static int app_start(struct app_action *app_args);
static int app_stop(struct app_action *app_args);
static int app_getinfo(struct app_action *app_args);
static int app_list(struct app_action *app_args);
static int app_out_version(struct app_action *app_args);

/* 
 * Convert relative path to absolute path and validate application name consistency
 * This function ensures file paths are properly resolved and app names match package names
 * @param app_args: Structure containing application action parameters
 * @param absolute_path: Output buffer for storing the resolved absolute path
 * @return: 0 on success, -1 on error (path resolution or name mismatch)
 */
static int check_appname_and_get_absolute_path(struct app_action *app_args, char *absolute_path) 
{
    int ret = 0;
    //判读是-f 还是 -p 参数
    if(0 != strlen(app_args->package_path))
    {
        //-f
        char pack_appname[DIR_SIZE];
        char *dot = NULL;
        // If the input path is already absolute (starts with '/'), just return it
        if (app_args->package_path[0] == '/') {
            strcpy(absolute_path, app_args->package_path);

            //检查安装包名字
            dot = strrchr(app_args->package_path, '/');
            if (dot != NULL) {
                strcpy(pack_appname, dot+1);
                dot = strchr(pack_appname, '-');
                if (dot != NULL) {
                    *dot = '\0'; // 将点替换为字符串结束符
                }
                
                if (strcmp(pack_appname, app_args->app_name) != 0) {
                    printf("appname and packname not match\n");
                    ret = -1;
                }
            }

        } else {
            // Get the current working directory
            char cwd[DIR_SIZE];
            if (getcwd(cwd, sizeof(cwd)) != NULL) {
                // Concatenate current directory with the relative path
                snprintf(absolute_path, DIR_SIZE, "%s/%s", cwd, app_args->package_path);
            } else {
                printf("getcwd funtion error\n");
                ret = -1;
            }

            //检查安装包名字
            strcpy(pack_appname, app_args->package_path);
            dot = strchr(pack_appname, '-');
            if (dot != NULL) {
                *dot = '\0'; // 将点替换为字符串结束符
            }
            if (strcmp(pack_appname, app_args->app_name) != 0) {
                printf("appname and packname not match\n");
                ret = -1;
            }
        }
    }
    else
    {
        //-p
        //检查是否为单独的pack_name
        char *dot = strchr(app_args->default_package, '/');
        if (dot != NULL) {
            printf("argv -p {packname} \n");
            ret = -1;
        }

        snprintf(absolute_path, DIR_SIZE, "%s/%s", APP_PACK_BACKUP, app_args->default_package);
        //获取appname
        strcpy(app_args->app_name, app_args->default_package);

        dot = strchr(app_args->app_name, '-');
        if (dot != NULL) {
            *dot = '\0'; // 将点替换为字符串结束符
        }
    }

    return ret;
}

/* 
 * Parse and process control action response messages from MQTT
 * This function interprets error codes and messages from application control operations
 * @param errorcode: Pointer to error code that will be updated based on response
 * @param result: Response message string containing operation result or error information
 */
static void control_action_message_dispose(int *errorcode, char *result)
{
    if (*errorcode) {
        if(strcmp(result, SUB_MESSAGE_TOKEN)==0)
        {
            printf("subtopic message token error\n");
            *errorcode = ERROR_SUB_MESSAGE_TOKEN_ERR;
        }
        else 
        {
            printf("errmsg: %s\n", result);
            if(strcmp(result, AUTHEN_FAIL)==0)
            {
                *errorcode = ERROR_AUTHERNTIFICATION_FAIL;
            }
            else if(strcmp(result, EXCUTE_ERROR)==0)
            {
                *errorcode = ERROR_EXCUTE_ERR;
            }
            else if(strcmp(result, APP_NOT_EXIST)==0)
            {
                *errorcode = ERROR_APP_NOT_EXIT;
            }
            else
            {
                printf("control_app_message  error\n");
                *errorcode = ERROR_APP_CONTROL_ERR;
            }
        }
    }
}

/* 
 * Parse and process application list information from JSON response
 * This function extracts application details from MQTT response and populates data structures
 * @param errorcode: Pointer to error code that indicates operation success/failure
 * @param message: JSON message string containing application list data
 * @param app_name: 2D array to store application names (can be NULL if not needed)
 * @param app_num: Pointer to store the number of applications found
 * @param printAppList: Boolean flag to control whether to print application details
 * @param query_appname: Specific application name to filter results (empty string for all)
 */
static void app_list_info_dispose(int *errorcode, char *message, char app_name[][64], int *app_num, bool printAppList, const char *query_appname)
{
    if (*errorcode)
    {
        if(strcmp(message, SUB_MESSAGE_TOKEN)==0)
        {
            printf("subtopic message token error\n");
            *errorcode = ERROR_SUB_MESSAGE_TOKEN_ERR;
        }
        else 
        {
            printf("errmsg: %s\n", message);
            *errorcode = ERROR_APP_APP_LIST_ERR;
            //printf("get_app_list_info message error\n");
        }
    }
    else
    {
        cJSON *root = cJSON_Parse(message);
        if (root != NULL) {
            // 获取data对象
            cJSON *data = cJSON_GetObjectItem(root, "data");
            if (data == NULL) {
                printf("No 'data' field found!\nmessage:%s",message);
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            // 获取applist数组
            cJSON *applist = cJSON_GetObjectItem(data, "applist");
            if (applist == NULL) {
                printf("No 'applist' field found!\n");
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            // 遍历applist数组中的每个元素（每个元素都是一个对象）
            *app_num = cJSON_GetArraySize(applist);
            if(*app_num >APP_MAX_AMOUNT)
            {
                printf("app_num: %d, over app amount limit %d!\n", *app_num, APP_MAX_AMOUNT);
                *app_num = APP_MAX_AMOUNT;
            } 

            cJSON *app = NULL;
            cJSON *appname = NULL;
            cJSON *appid = NULL;
            cJSON *appversion = NULL;
            cJSON *appverdate = NULL;
            int checkapp = 0;
            for (int i = 0; i < *app_num; i++) {
                app = cJSON_GetArrayItem(applist, i);

                // 获取appname键的值
                appname = cJSON_GetObjectItem(app, "appname");
                if(appname == NULL)
                {
                    continue;
                }

                if (app_name != NULL) {
                    strcpy(app_name[i], appname->valuestring);
                }

                if(printAppList)
                {
                    if(strlen(query_appname) > 0)
                    {
                        if(strcmp(query_appname,appname->valuestring) == 0)
                        {
                            printf("appname: %s\n", appname->valuestring);
                            // 获取appid键的值
                            appid = cJSON_GetObjectItem(app, "appid");
                            if (appid != NULL) {
                                printf("appid: %s\n", appid->valuestring);
                            }

                            // 获取appversion键的值
                            appversion = cJSON_GetObjectItem(app, "appversion");
                            if (appversion != NULL) {
                                printf("appversion: %s\n", appversion->valuestring);
                            }

                            // 获取appverdate键的值
                            appverdate = cJSON_GetObjectItem(app, "appverdate");
                            if (appverdate != NULL) {
                                printf("appverdate: %s\n", appverdate->valuestring);
                            }
                            printf("\n");

                            checkapp++;
                        }

                        if(i == *app_num-1 && checkapp == 0)
                        {
                            printf("query_appname: %s not exist\n", query_appname);
                            *errorcode = ERROR_APP_NOT_EXIT;
                        }
                    }
                    else
                    {
                        printf("appname: %s\n", appname->valuestring);
                        // 获取appid键的值
                        appid = cJSON_GetObjectItem(app, "appid");
                        if (appid != NULL) {
                            printf("appid: %s\n", appid->valuestring);
                        }

                        // 获取appversion键的值
                        appversion = cJSON_GetObjectItem(app, "appversion");
                        if (appversion != NULL) {
                            printf("appversion: %s\n", appversion->valuestring);
                        }

                        // 获取appname键的值
                        appverdate = cJSON_GetObjectItem(app, "appverdate");
                        if (appverdate != NULL) {
                            printf("appverdate: %s\n", appverdate->valuestring);
                        }
                        printf("\n");
                    }
                }
            }

            // 释放解析的JSON
            cJSON_Delete(root);
        }
        else
        {
            printf("cJSON_Parse message error\n");
            printf("ERR message: %s\n", message);
            *errorcode = ERROR_JSON_PARSE_ERR;
        }
    }
}

/* 
 * Parse and process application status information from JSON response
 * This function extracts runtime status details like state, CPU usage, and memory usage
 * @param errorcode: Pointer to error code that indicates operation success/failure
 * @param message: JSON message string containing application status data
 * @param query_appname: Specific application name to filter results (empty string for all)
 */
static void app_status_info_dispose(int *errorcode, char *message, const char *query_appname)
{
    int app_num = 0;
    if (*errorcode)
    {
        if(strcmp(message, SUB_MESSAGE_TOKEN)==0)
        {
            printf("subtopic message token error\n");
            *errorcode = ERROR_SUB_MESSAGE_TOKEN_ERR;
        }
        else 
        {
            printf("errmsg: %s\n", message);
            *errorcode = ERROR_APP_APP_STATUS_ERR;
            //printf("get_app_list_info message error\n");
        }
    }
    else
    {
        cJSON *root = cJSON_Parse(message);
        if (root != NULL) {
            // 获取data对象
            cJSON *data = cJSON_GetObjectItem(root, "data");
            if (data == NULL) {
                printf("No 'data' field found!\nmessage:%s",message);
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            // 获取applist数组
            cJSON *applist = cJSON_GetObjectItem(data, "applist");
            if (applist == NULL) {
                printf("No 'applist' field found!\n");
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            // 遍历applist数组中的每个元素（每个元素都是一个对象）
            app_num = cJSON_GetArraySize(applist);
            if(app_num >APP_MAX_AMOUNT)
            {
                printf("app_num: %d, over app amount limit %d!\n", app_num, APP_MAX_AMOUNT);
                app_num = APP_MAX_AMOUNT;
            } 

            cJSON *app = NULL;
            cJSON *appname = NULL;
            cJSON *state = NULL;
            cJSON *CPUusage = NULL;
            cJSON *memoryusage = NULL;
            int checkapp = 0;
            for (int i = 0; i < app_num; i++) {
                app = cJSON_GetArrayItem(applist, i);

                // 获取appname键的值
                appname = cJSON_GetObjectItem(app, "appname");
                if(appname == NULL)
                {
                    continue;
                }

                if(strlen(query_appname) > 0)
                {
                    if(strcmp(query_appname,appname->valuestring) == 0)
                    {
                        printf("appname: %s\n", appname->valuestring);
                        // 获取appid键的值
                        state = cJSON_GetObjectItem(app, "state");
                        if (state != NULL) {
                            printf("state: %s\n", state->valuestring);
                        }

                        // 获取appversion键的值
                        CPUusage = cJSON_GetObjectItem(app, "CPUusage");
                        if (CPUusage != NULL) {
                            printf("CPUusage: %s\n", CPUusage->valuestring);
                        }

                        // 获取appverdate键的值
                        memoryusage = cJSON_GetObjectItem(app, "memoryusage");
                        if (memoryusage != NULL) {
                            printf("memoryusage: %s\n", memoryusage->valuestring);
                        }
                        printf("\n");

                        checkapp++;
                    }

                    if(i == app_num-1 && checkapp == 0)
                    {
                        printf("query_appname: %s not exist\n", query_appname);
                        *errorcode = ERROR_APP_NOT_EXIT;
                    }
                }
                else
                {
                    printf("appname: %s\n", appname->valuestring);
                    // 获取appid键的值
                    state = cJSON_GetObjectItem(app, "state");
                    if (state != NULL) {
                        printf("state: %s\n", state->valuestring);
                    }

                    // 获取appversion键的值
                    CPUusage = cJSON_GetObjectItem(app, "CPUusage");
                    if (CPUusage != NULL) {
                        printf("CPUusage: %s\n", CPUusage->valuestring);
                    }

                    // 获取appname键的值
                    memoryusage = cJSON_GetObjectItem(app, "memoryusage");
                    if (memoryusage != NULL) {
                        printf("memoryusage: %s\n", memoryusage->valuestring);
                    }
                    printf("\n");
                }
            }

            // 释放解析的JSON
            cJSON_Delete(root);
        }
        else
        {
            printf("cJSON_Parse message error\n");
            printf("ERR message: %s\n", message);
            *errorcode = ERROR_JSON_PARSE_ERR;
        }
    }
}

/* 
 * Parse and process application rights and permissions information from JSON response
 * This function extracts resource allocation details like CPU limits, memory limits, and network permissions
 * @param errorcode: Pointer to error code that indicates operation success/failure
 * @param message: JSON message string containing application rights data
 * @param appname: Application name for which rights information is being displayed
 */
static void app_right_info_dispose(int *errorcode, char *message, const char *appname)
{
    if (*errorcode)
    {
        if(strcmp(message, SUB_MESSAGE_TOKEN)==0)
        {
            printf("subtopic message token error\n");
            *errorcode = ERROR_SUB_MESSAGE_TOKEN_ERR;
        }
        else 
        {
            printf("errmsg: %s\n", message);
            *errorcode = ERROR_APP_APP_RIGHTS_ERR;
            //printf("get_app_list_info message error\n");
        }
    }
    else
    {
        cJSON *root = cJSON_Parse(message);
        if (root != NULL) {
            // 获取data对象
            cJSON *data = cJSON_GetObjectItem(root, "data");
            if (data == NULL) {
                printf("No 'data' field found!\nmessage:%s",message);
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            // 获取apprights节点
            cJSON *apprights = cJSON_GetObjectItem(data, "apprights");
            if (apprights == NULL) {
                printf("No 'apprights' field found!\n");
                cJSON_Delete(root);
                *errorcode = ERROR_JSON_MESSAGE_INFO_ERR;
                return;
            }

            printf("appname: %s\n", appname);

            // 遍历并输出 apprights 中的数据
            cJSON *item = NULL;

            // 遍历 "CPUrate"
            item = cJSON_GetObjectItem(apprights, "CPUrate");
            if (item) {
                printf("CPUrate: %s\n", item->valuestring);
            }

            // 遍历 "memory"
            item = cJSON_GetObjectItem(apprights, "memory");
            if (item) {
                printf("memory: %s\n", item->valuestring);
            }

            // 遍历 "paramflash"
            item = cJSON_GetObjectItem(apprights, "paramflash");
            if (item) {
                printf("paramflash: %s\n", item->valuestring);
            }

            // 遍历 "dataflash"
            item = cJSON_GetObjectItem(apprights, "dataflash");
            if (item) {
                printf("dataflash: %s\n", item->valuestring);
            }

            // 遍历 "permitports"
            item = cJSON_GetObjectItem(apprights, "permitports");
            if (item && cJSON_IsArray(item)) {
                printf("permitports: ");
                int array_size = cJSON_GetArraySize(item);
                for (int i = 0; i < array_size; i++) {
                    cJSON *port = cJSON_GetArrayItem(item, i);
                    if (port) {
                        printf("%s ", port->valuestring);
                    }
                }
                printf("\n");
            }

            // 遍历 "permitcmds"
            item = cJSON_GetObjectItem(apprights, "permitcmds");
            if (item && cJSON_IsArray(item)) {
                printf("permitcmds: ");
                int array_size = cJSON_GetArraySize(item);
                for (int i = 0; i < array_size; i++) {
                    cJSON *cmd = cJSON_GetArrayItem(item, i);
                    if (cmd) {
                        printf("%s ", cmd->valuestring);
                    }
                }
                printf("\n");
            }

            // 遍历 "addiproute"
            item = cJSON_GetObjectItem(apprights, "addiproute");
            if (item) {
                printf("addiproute: %s\n", item->valuestring);
            }

            // 遍历 "permitRequest"
            item = cJSON_GetObjectItem(apprights, "permitRequest");
            if (item && cJSON_IsArray(item)) {
                printf("permitRequest: ");
                int array_size = cJSON_GetArraySize(item);
                for (int i = 0; i < array_size; i++) {
                    cJSON *request = cJSON_GetArrayItem(item, i);
                    if (request) {
                        printf("%s ", request->valuestring);
                    }
                }
                printf("\n");
            }

            printf("\n");

            // 释放解析的JSON
            cJSON_Delete(root);
        }
        else
        {
            printf("cJSON_Parse message error\n");
            printf("ERR message: %s\n", message);
            *errorcode = ERROR_JSON_PARSE_ERR;
        }
    }
}

/**
 * @brief  获取pack名
 * Extract the package name from a package file path by removing directory path and file extension
 * This function validates that the path ends with .pack and extracts the base filename
 * @param  packpath pack所在的路径。The full path to the package file
 * @param  packname pack的名字存储指针 Output buffer for storing the extracted package name
 * @retval  成功返回0，失败返回-1. Returns 0 on success, -1 on failure (invalid path or format)
*/
static int check_app_packname(const char* packpath, char *packname) {
    if (packpath == NULL || packname == NULL) {
        return -1; // 输入路径或输出指针为空，返回失败
    }

    // 检查packpath是否以.pack结尾
    const char* suffix = ".pack";
    size_t path_length = strlen(packpath);
    size_t suffix_length = strlen(suffix);
    
    if (path_length < suffix_length || strcmp(packpath + path_length - suffix_length, suffix) != 0) {
        return -1; // 如果不以.pack结尾，返回失败
    }

    // 查找最后一个斜杠的位置
    const char* last_slash = strrchr(packpath, '/');
    if (last_slash == NULL) {
        last_slash = packpath; // 如果没有斜杠，使用整个路径
    } else {
        last_slash++; // 移动到斜杠后面
    }

    // 查找最后一个点的位置
    const char* last_dot = strrchr(last_slash, '.');
    if (last_dot == NULL || last_dot == last_slash) {
        return -1; // 如果没有找到点，或者点在pack名前面，返回失败
    }

    // 计算pack名的长度
    size_t packname_length = last_dot - last_slash;
    if (packname_length == 0) {
        return -1; // pack名为空，返回失败
    }

    // 拷贝pack名到packname指向的空间
    strncpy(packname, last_slash, packname_length);
    packname[packname_length] = '\0'; // 添加字符串结束符

    return 0; // 成功返回0
}

/* 
 * Create or recreate the temporary working directory for application operations
 * This function ensures the temporary directory exists by deleting and recreating it if necessary
 * @return: 0 on success, -1 on failure (directory creation or deletion error)
 */
// Function to check if a directory exists, and delete it if it does, then recreate it
static int create_option_using_directory(void) {
    struct stat st = {0};
    int ret = 0;
    // Check if the directory exists
    if (stat(UZIP_DIR, &st) == 0) {
        // Directory exists, try to remove it
        ret = shell_system("rm -rf %s",UZIP_DIR);
        if (ret != 0) {
            fprintf(stderr,"rmdir %s failed.\n",UZIP_DIR);
            return -1;
        } 
    }

    // Create the directory again
    ret = shell_system("mkdir %s",UZIP_DIR);
    if (ret != 0) {
        fprintf(stderr, "mkdir %s failed\n",UZIP_DIR);
        return -1;
    }

    return ret;
}

/**
 * @brief 在指定目录下切分pack文件为.tgz 和 cycdata两部分
 * Split a .pack file into .tgz and checksum parts by removing the last 32 bytes (signature)
 * This function handles the binary separation of package files for further processing
 * @param  packpath pack所在的路径。例如：/tmp/app/sys.tasksched-V1.0.7-20241113.pack
 * The full path to the input .pack file
 * @param  tgz_filename Output buffer for the generated .tgz file path
 * @retval 成功返回0，失败返回-1。Returns 0 on success, -1 on failure (file I/O error)
 */
static int cut_app_pack(const char* packpath,char *tgz_filename)
{
    FILE *pack_file = NULL;
    FILE *tgz_file = NULL;
    struct stat st;
    long total_size;
    char *dot_pos;

    // 获取文件大小
    if (stat(packpath, &st) != 0) {
        perror("Unable to stat pack file");
        return -1;
    }
    total_size = st.st_size;

    // 打开源pack文件
    pack_file = fopen(packpath, "rb");
    if (pack_file == NULL) {
        perror("Unable to open pack file");
        return -1;
    }

    // 去掉 .pack 扩展名，并构造目标文件名
    dot_pos = strrchr(packpath, '.');
    if (dot_pos != NULL && strcmp(dot_pos, ".pack") == 0) {
        // 如果找到 .pack 后缀
        size_t base_len = dot_pos - packpath;  // 获取去掉 .pack 后的文件名长度
        strncpy(tgz_filename, packpath, base_len);
        tgz_filename[base_len] = '\0';  // 添加字符串终止符
        snprintf(tgz_filename + base_len, DIR_SIZE - base_len, ".tgz");
    } else {
        // 如果没有找到 .pack 后缀，直接使用原始路径
        snprintf(tgz_filename, DIR_SIZE, "%s.tgz", packpath);
    }

    // 打开tgz文件
    tgz_file = fopen(tgz_filename, "wb");
    if (tgz_file == NULL) {
        perror("Unable to create tgz file");
        fclose(pack_file);
        return -1;
    }

    // 计算tgz文件大小（pack文件大小减去32个字节校验值）
    long tgz_size = total_size - 32;

    // 拷贝 .tgz 部分
    char buffer[CHUNK_SIZE];
    size_t bytes_to_read = tgz_size;
    size_t bytes_read;
    while (bytes_to_read > 0) {
        bytes_read = fread(buffer, 1, (bytes_to_read < CHUNK_SIZE) ? bytes_to_read : CHUNK_SIZE, pack_file);
        if (bytes_read == 0) {
            if (feof(pack_file)){
                break;
            } 
            perror("Error reading pack file");
            fclose(pack_file);
            fclose(tgz_file);
            return -1;
        }
        fwrite(buffer, 1, bytes_read, tgz_file);
        bytes_to_read -= bytes_read;
    }

    // 关闭文件
    fclose(pack_file);
    fclose(tgz_file);
    return 0;
}

/* 
 * Extract a tar.gz package to the temporary directory for inspection and processing
 * This function uses the system tar command to decompress application packages
 * @param package_path: Path to the .tgz package file to extract
 * @param appname: Application name (currently unused parameter)
 * @return: 0 on success, -1 on failure (extraction command failed)
 */
// Function to extract the package (tar.gz) to the UZIP_DIR directory
static int extract_package_to_tmp(const char *package_path,const char*appname) {
    char command[256];

    // Construct the tar extraction command
    snprintf(command, sizeof(command), "tar -xzvf %s -C %s >> /dev/null", package_path,UZIP_DIR);

    // Execute the command
    int ret = system(command);
    if (ret == -1) {
        perror("Failed to execute tar command");
        return -1;
    }

    return 0;
}

/* 
 * Check if AppProfile.json configuration file exists in the temporary extraction directory
 * This function validates that the extracted package contains the required configuration file
 * @return: 0 if AppProfile.json exists, -1 if not found
 */
// Function to check if AppProfile.json exists in the JUNIOR_UNZIP_PATH or JUNIOR_UNZIP_PATH/{appname} directories
static int check_app_file(void) {
    char tmp_dir[256];
    struct stat st;

    // Check if AppProfile.json exists in JUNIOR_UNZIP_PATH
    snprintf(tmp_dir, sizeof(tmp_dir), "%s/AppProfile.json",UZIP_DIR);
    if (stat(tmp_dir, &st) != 0) {
        printf("NoFound AppProfile.json in %s\n",UZIP_DIR);
        return -1;
    }
    return 0;
}

/* 
 * Install an application by processing its package file and sending installation command
 * This is the main installation function that orchestrates the entire installation process
 * @param app_args: Structure containing application installation parameters
 * @return: Error code indicating installation success or specific failure reason
 */
//安装应用
static int app_install(struct app_action *app_args){
    char absolute_path[DIR_SIZE];
    char pack_appname[DIR_SIZE];
    const char *appsign = "reserved";
    char result[EXEC_MES_BUFF_LEN+1] = {0};
    char app_pack_name[MAX_NODES] = {0};
    char app_profile_tmp_path[DIR_SIZE] = {0};
    char app_install_dir[DIR_SIZE] = {0};
    char startfilepath[MAX_NODES] = {0};
    char tgz_filepath[DIR_SIZE];
    char app_name[64] = {0};

    int ret = 0;

    //获取绝对路径
    ret = check_appname_and_get_absolute_path(app_args, absolute_path);
    if (ret) {
        printf("check appname or get package path error\n");
        ret = ERROR_GET_ABSOLUTE_PATH_ERR;
        return ret;
    }

    if(is_file_exist(absolute_path)!=0)
    {
        printf("package file no exist\n");
        ret = ERROR_PACKAGE_NO_EXIST_ERR;
        return ret;
    }

    //检查pack名
    if(check_app_packname(absolute_path,app_pack_name))
    {
        printf("check_app_packname %s is error\n",absolute_path);
        ret = ERROR_APP_PACK_NAME_ERR;
        return ret;
    }    

    //检测是否存在用到的文件夹，没有则创建
    if(create_option_using_directory())
    {
        printf("create_option_using_directory error\n");
        ret = ERROR_CREATE_APPINSTALL_TMPDIR_ERR;
        return ret;
    }

    //拷贝文件到 UZIP_DIR 
    if (shell_system("cp %s %s/",absolute_path,UZIP_DIR)) 
    {
        fprintf(stderr, "cp %s to the %s corresponding directory failed \n",absolute_path,UZIP_DIR); 
        ret = ERROR_CP_APP_PACK_TO_TARGET_DIR_ERROR;
        goto ERROR_TMP;
    }

    snprintf(app_profile_tmp_path, sizeof(app_profile_tmp_path), "%s/%s.pack",UZIP_DIR, app_pack_name);
    //拆分.pack文件
    if(cut_app_pack(app_profile_tmp_path,tgz_filepath))
    {
        fprintf(stderr, "cut_app_pack %s is error\n",app_profile_tmp_path);
        ret = ERROR_CAT_APP_PACK_ERROR;
        goto ERROR_TMP;
    }

    //解压文件
    if(extract_package_to_tmp(tgz_filepath,app_args->app_name))
    {
        fprintf(stderr, "extract_package_to_tmp error\n");
        ret = ERROR_PACKAGE_DECOMPRESS_ERR;
        goto ERROR_TMP;
    }

    //查找文件APPPROFILE文件
    if(check_app_file())
    {
        fprintf(stderr, "check App_file error\n");
        ret = ERROR_CHAER_APP_FILE_ERROR;
        goto ERROR_TMP;
    }

    memset(app_profile_tmp_path,0,sizeof(app_profile_tmp_path));
    snprintf(app_profile_tmp_path, sizeof(app_profile_tmp_path), "%s/AppProfile.json",UZIP_DIR, app_args->app_name);    

    //获取appProfile信息
    if(open_appprofile_ctl(app_profile_tmp_path))
    {
        fprintf(stderr, "open_appprofile_ctl error\n");
        ret = ERROR_OPEN_APPPROFILE_CTL_ERROR;
        goto ERROR_TMP;
    }

    if(getAppProfileInfo("appInfo",APPNAME,app_name)){
        fprintf(stderr, "getAppProfileInfo %s error\n",APPNAME);
        ret = ERROR_APPPROFILE_GET_APPNAME_ERROR;
        goto ERROR_EXEC;
    }

    //对比名字是否一致
    if(strcmp(app_args->app_name,app_name))
    {
        printf("app_name inconformity %s :  %s\n",app_args->app_name,app_name);
        ret = ERROR_APPNAME_MISMATCHING;
        goto ERROR_EXEC;
    }

    shell_system("rm -rf %s",UZIP_DIR);

    //安装命令
    ret = install_app_message(app_args->app_name, absolute_path, appsign, &result);
    if (ret) {
        if(strcmp(result, SUB_MESSAGE_TOKEN)==0)
        {
            printf("subtopic message token error\n");
            ret = ERROR_SUB_MESSAGE_TOKEN_ERR;
        }
        else
        {
            printf("errmsg: %s\n", result);
            if(strcmp(result, AUTHEN_FAIL)==0)
            {
                ret = ERROR_AUTHERNTIFICATION_FAIL;
            }
            else if(strcmp(result, FILE_SIGN_ERROR)==0)
            {
                ret = ERROR_FILE_SIGNATURE_ERR;
            }
            else if(strcmp(result, FILE_NOT_EXIST)==0)
            {
                ret = ERROR_FILE_NOT_EXIT;
            }
            else
            {
                printf("install_app_message  error\n");
                ret = ERROR_INSTALL_APPMANGE_ERR;
            }
        }
    }

ERROR_EXEC:
    close_appprofile_ctl();

ERROR_TMP:
    if(is_dir_exist(UZIP_DIR) == 0)
    {
        shell_system("rm -rf %s",UZIP_DIR);
    }

    return ret;
}

/* 
 * Uninstall an application by sending uninstall command to application management system
 * This function requests the removal of an installed application
 * @param app_args: Structure containing application uninstall parameters
 * @return: Error code indicating uninstallation success or specific failure reason
 */
//卸载应用
static int app_uninstall(struct app_action *app_args){
    int ret = 0;
    const char *appsign = "reserved";
    char result[EXEC_MES_BUFF_LEN+1] = {0};

    ret = control_app_message(app_args->app_name, APP_UNINSTALL, appsign, &result);
    control_action_message_dispose(&ret, &result);

    return ret;
}

/* 
 * Start a previously installed application by sending enable command
 * This function requests the application management system to launch the application
 * @param app_args: Structure containing application start parameters
 * @return: Error code indicating start operation success or specific failure reason
 */
static int app_start(struct app_action *app_args){
    int ret = 0;
    const char *appsign = "reserved";
    char result[EXEC_MES_BUFF_LEN+1] = {0};

    ret = control_app_message(app_args->app_name, APP_ENABLE, appsign, &result);
    control_action_message_dispose(&ret, &result);

    return ret;
}

/* 
 * Stop a running application by sending disable command
 * This function requests the application management system to terminate the application
 * @param app_args: Structure containing application stop parameters
 * @return: Error code indicating stop operation success or specific failure reason
 */
static int app_stop(struct app_action *app_args){
    int ret = 0;
    const char *appsign = "reserved";
    char result[EXEC_MES_BUFF_LEN+1] = {0};

    ret = control_app_message(app_args->app_name, APP_DISABLE, appsign, &result);
    control_action_message_dispose(&ret, &result);

    return ret;
}

/* 
 * Retrieve and display application information including rights and permissions
 * This function can show information for a specific application or all applications
 * @param app_args: Structure containing application information parameters
 * @return: Error code indicating information retrieval success or specific failure reason
 */
static int app_getinfo(struct app_action *app_args){
    //输出应用版本
    int ret = 0;
    int app_num = 0;
    char result[MESSAGE_MAX_LEN+1] = {0};
    char app_name[APP_MAX_AMOUNT][64];

    if(strlen(app_args->app_name) > 0)
    {
        ret = get_app_rights_info(app_args->app_name, &result);
        app_right_info_dispose(&ret, &result, app_args->app_name);
        return ret;
    }
    else
    {
        ret = get_app_list_info(DEFAULE_APP_NAME, &result);
        app_list_info_dispose(&ret, &result, app_name, &app_num, false, NULL);
        if(ret)
        {
            printf("app_right get_app_list_info error\n");
            return ret;
        }
        else
        {
            printf("app num: %d\n\n", app_num);
        }

        for(int i = 0; i < app_num; i++)
        {
            memset(&result,'\0',sizeof(result));
            ret = get_app_rights_info(app_name[i], &result);
            app_right_info_dispose(&ret, &result, app_name[i]);

            if(ret)
            {
                printf("%s message error: %s\n", app_name[i], result);
                printf("\n");
            }
        }
    }

    return ret;
}

/* 
 * List application status information including running state and resource usage
 * This function displays current status of applications (running, CPU usage, memory usage)
 * @param app_args: Structure containing application list parameters
 * @return: Error code indicating status retrieval success or specific failure reason
 */
static int app_list(struct app_action *app_args){
    //输出应用版本
    int ret = 0;
    int app_num = 0;
    char result[MESSAGE_MAX_LEN+1] = {0};

    ret = get_app_status_info(DEFAULE_APP_NAME, &result);
    app_status_info_dispose(&ret, &result, app_args->app_name);
    return ret;
}

/* 
 * Output application version information for specific or all applications
 * This function displays version details including app ID, version number, and version date
 * @param app_args: Structure containing application version parameters
 * @return: Error code indicating version retrieval success or specific failure reason
 */
static int app_out_version(struct app_action *app_args){
    //输出应用版本
    int ret = 0;
    int app_num = 0;
    char result[MESSAGE_MAX_LEN+1] = {0};

    ret = get_app_list_info(DEFAULE_APP_NAME, &result);
    app_list_info_dispose(&ret, &result, NULL, &app_num, true, app_args->app_name);
    return ret;
}

/* 
 * Execute the requested application action based on command line arguments
 * This is the main entry point for application control operations that routes to specific functions
 * @param app_args: Structure containing all application action parameters and flags
 * @return: Error code indicating operation success or specific failure reason
 */
int appaction_exec(struct app_action *app_args){
    int ret = -1;
    //验证配置是否正确
    ret = appaction_check(app_args);

    if(!ret){

        //执行安装
        if (app_args->set_install){
            // 检查是否在重入
            if (is_program_running(PROGRAM_NAME)) {
                printf("appctl program is already running\n");
                return ERROR_PROFRAAM_RUNNING;
            }

            ret = app_install(app_args);
            if(ret == 0){
                printf("%s install success\n",app_args->app_name);
            }
            else
            {
                printf("%s install fail\n",app_args->app_name);
            }
        }
        else if (app_args->set_uninstall){
            // 检查是否在重入
            if (is_program_running(PROGRAM_NAME)) {
                printf("appctl program is already running\n");
                return ERROR_PROFRAAM_RUNNING;
            }
            ret = app_uninstall(app_args);
            if(ret == 0){
                printf("%s uninstall success\n",app_args->app_name);
            }
            else
            {
                printf("%s uninstall fail\n",app_args->app_name);
            }
        }
        else if (app_args->set_start){
            // 检查是否在重入
            if (is_program_running(PROGRAM_NAME)) {
                printf("appctl program is already running\n");
                return ERROR_PROFRAAM_RUNNING;
            }

            ret = app_start(app_args);
            if(ret == 0){
                printf("%s start success\n",app_args->app_name);
            }
            else
            {
                printf("%s start fail\n",app_args->app_name);
            }
        }
        else if (app_args->set_stop){
            // 检查是否在重入
            if (is_program_running(PROGRAM_NAME)) {
                printf("appctl program is already running\n");
                return ERROR_PROFRAAM_RUNNING;
            }

            ret = app_stop(app_args);
            if(ret == 0){
                printf("%s stop success\n",app_args->app_name);
            }
            else
            {
                printf("%s stop fail\n",app_args->app_name);
            }
        }
        else if(app_args->set_getinfo){
            ret = app_getinfo(app_args);
        }
        else if(app_args->set_list){
            ret = app_list(app_args);
        }
        else if(app_args->set_out_version){
            ret = app_out_version(app_args);
        }
    }
    else{
        printf("appaction_check error,please cheak command info\n");
    }

    return ret;
}

/* 
 * Validate application action parameters and check for logical conflicts
 * This function ensures command line arguments are consistent and complete
 * @param app_args: Structure containing all application action parameters and flags
 * @return: Error code indicating parameter validity or specific validation error
 */
int appaction_check(struct app_action *app_args){
    int sum = 0,ret = 0;
    //检测-i,-s,-u,-S,-l,-V,-I命令是否冲突
    sum = app_args->set_install + app_args->set_start + app_args->set_stop + app_args->set_uninstall + \
          app_args->set_list + app_args->set_out_version + app_args->set_getinfo;
    if (sum > 1)
    {
        ret = ERROR_ARGS_ERR;
    }
    if ((app_args->set_stop || app_args->set_start||app_args->set_uninstall) && (strlen(app_args->app_name)==0))
    {
        ret = ERROR_ARGS_APPNAME_NOT_EXIST_ERR;
    }
    if (app_args->set_install)
    {
        if((strlen(app_args->package_path)==0) && (strlen(app_args->default_package)==0))
        {
            ret = ERROR_ARGS_PACKFILEPATH_NOT_EXIST_ERR;
        }
        else if ((strlen(app_args->package_path)!=0) && (strlen(app_args->app_name)==0))
        {
            ret = ERROR_ARGS_APPNAME_NOT_EXIST_ERR;
        }
    }
    return ret;
}